#region Usings

using System;
using System.Collections.Generic;
using System.Web;
using Karma.Framework.Core.Services.Invoker;
using log4net;
using Newtonsoft.Json;
using Karma.Framework.Core.Domain.Tools.Import.Configuration;
using Karma.Framework.Core.IoC;

#endregion

namespace Karma.Framework.Core.Domain.Tools.Import.Handler
{
    public class ImporterHandler : IHttpHandler
    {
        private static ILog LOG = LogManager.GetLogger(typeof (ImporterHandler).Name);

        #region IHttpHandler Members

        public void ProcessRequest(HttpContext context)
        {
            if (context.Request.HttpMethod.Equals("GET"))
            {
                DoGetLayout(context);
            }
            if (context.Request.HttpMethod.Equals("POST"))
            {
                DoPostLayout(context);
            }
        }

        public bool IsReusable
        {
            get { return false; }
        }

        #endregion

        private void DoGetLayout(HttpContext context)
        {
            var entityTypeName = ExtractEntity();
            if (LOG.IsDebugEnabled)
            {
                LOG.Debug(string.Format("Entity layout requested: {0}", entityTypeName));
            }
            var service = IoCFactory.Resolve<IImporterService>();
            var entity =
                Type.GetType(entityTypeName + ", " + ImporterConfiguration.DomainAssembly);
            if (LOG.IsDebugEnabled)
            {
                LOG.Debug(string.Format("Entity layout requested: {0}", entityTypeName));
            }
            service.GetLayout(entity);
        }

        private void DoPostLayout(HttpContext context)
        {
            var entityTypeName = ExtractEntity();
            try
            {
                if (LOG.IsDebugEnabled)
                {
                    LOG.Debug(string.Format("Entity layout requested: {0}", entityTypeName));
                }
                var service = IoCFactory.Resolve<IImporterService>();
                var entity =
                    Type.GetType(entityTypeName + ", " + ImporterConfiguration.DomainAssembly);
                if (LOG.IsDebugEnabled)
                {
                    LOG.Debug(string.Format("Entity layout requested: {0}", entityTypeName));
                }
                var file = context.Request.Files[0];
                if (LOG.IsDebugEnabled)
                {
                    LOG.Debug(string.Format("The uploaded file: [Name]: {0}, [Len]: {1}", file.FileName, file.ContentLength));
                }
                using (var stream = file.InputStream)
                {
                    context.Response.ContentType = "text/html";
                    var summary = service.Import(entity, stream);
                    var json = JsonConvert.SerializeObject(summary, Formatting.Indented, new JsonSerializerSettings
                    {
                        NullValueHandling =
                            NullValueHandling.
                            Include,
                        DefaultValueHandling =
                            DefaultValueHandling.
                            Include,
                        Converters = new List<JsonConverter> { new ErrorDescriptionConverter() }
                    });
                    if (LOG.IsDebugEnabled)
                    {
                        LOG.Debug(string.Format("Import summary: {0}", json));
                    }
                    context.Response.Write(json);
                }
            }
            catch (Exception e)
            {
                LOG.Error("", e);
                e = e.InnerException ?? e;
                var report = !(e.GetType() == typeof(ApplicationException));
                var response = e.InnerException != null
                                   ?
                                       new ServiceResponse(
                                           string.Empty, e.InnerException.Message,
                                           e.InnerException.StackTrace, report)
                                   : new ServiceResponse(
                                         string.Empty, e.Message, e.StackTrace, report);
                var json = JsonConvert.SerializeObject(response, Formatting.Indented, new JsonSerializerSettings
                {
                    NullValueHandling =
                        NullValueHandling.
                        Include,
                    DefaultValueHandling =
                        DefaultValueHandling.
                        Include,
                    Converters = new List<JsonConverter> { new ErrorDescriptionConverter() }
                });
                if (LOG.IsDebugEnabled)
                {
                    LOG.Debug(string.Format("Import summary: {0}", json));
                }
                context.Response.Write(json);
            }
        }

        private static string ExtractEntity()
        {
            var output = HttpContext.Current.Request.RawUrl;
            if (LOG.IsDebugEnabled)
            {
                LOG.Debug(string.Format("RawURL: {0}", output));
            }
            var subPos = output.IndexOf("/Importer/");
            subPos = subPos + 10;
            return output.Substring(subPos);
        }
    }
}